package org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.measure;

import java.util.List;

import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.TrustedRelationship;
import org.cytoscape.myapp.cytoscape_app_v1.internal.metrics.domain.UserPositionMapping;


public class StructuralCohesion {

	private List<TrustedRelationship> trustedRelationships;
	private UserPositionMapping mapping;

	public StructuralCohesion(UserPositionMapping mapping, List<TrustedRelationship> trustedRelationships) {
		this.mapping=mapping;
		this.trustedRelationships=trustedRelationships;
	}

	/**
	 * Return the Structural Cohesion Matrix
	 * @return double[][]
	 */
	public double[][] getStCMatrix() {
		double[][] stc=new double[this.mapping.getUsers().size()][this.mapping.getUsers().size()];
		double[][] p=createProbabilities();
		for (int i = 0; i < this.mapping.getUsers().size(); i++) {
			for (int j = 0; j < this.mapping.getUsers().size(); j++) {
				if(i!=j){
					double prod=getProductoria(i,j,p);
					double cohesion=1-(1-p[i][j])*prod;
					stc[i][j]=cohesion;
				}
			}
		}
		return stc;
	}

	private double getProductoria(int i, int j, double[][] p) {
		double prod=1;
		for (int k = 0; k < this.mapping.getUsers().size(); k++) {
			if((k!=j)&&(k!=i)){
				prod*=(1-(p[i][k]*p[k][j]));
			}
		}
		return prod;
	}

	private double[][] createProbabilities() {
		double[][] p=new double[this.mapping.getUsers().size()][this.mapping.getUsers().size()];
		for(int i=0;i<this.mapping.getUsers().size();i++){
			for(int j=0;j<this.mapping.getUsers().size();j++){
				if(j!=i){
					double nom=getTrustedRelationship(mapping.getUserIdByPosition(i),mapping.getUserIdByPosition(j));
					if(nom!=0.0){
						double den=getDenominator(mapping.getUserIdByPosition(i));
						p[i][j]=nom/den;
					}
				}
			}
		}
		return p;
	}

	private double getTrustedRelationship(String userId1, String userId2) {
		for (TrustedRelationship tr : trustedRelationships) {
			if(tr.getIdUser1().equals(userId1)&&tr.getIdUser2().equals(userId2))
				return tr.getTrValue();
		}
		return 0.0;
	}

	private double getDenominator(String userId) {
		double sum=0;
		for(TrustedRelationship tr : trustedRelationships){
			if(tr.getIdUser1().equals(userId))
				sum+=tr.getTrValue();
		}
		return sum;
	}
}
